#pragma once

#include "DataStructure/Common/Out.h"
#include "Utility/Algebra/Point.h"
#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Input/Material/ThermalMaterial.h"
#include "SGFem/ElementCalculator/Common/ElementCalculatorExport.h"
#include "SGFem/ElementCalculator/Interface/IElementCalculator.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN
class ElementCalculator_DECLSPEC CHBDYGAREA3Calculator : public SG::FEMSolver::Element::IElementCalculator
{
public:
    CHBDYGAREA3Calculator () = default;
    virtual ~CHBDYGAREA3Calculator () = default;
    /// @brief 计算和节点坐标无关的变量
    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) override;

    /** @brief 计算单元面对流刚度矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] material 材料特性
     * @param [out] ke2 单元边对流刚度矩阵
    */
    void ComputeConvStiffness
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::FEM::ThermalMaterial& material,
    _OUT SG::Algebra::Matrix& ke2
    );
    
    /** @brief 计算单元面对流刚度矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] h 单元节点上对流换热系数
     * @param [out] ke2 单元边对流刚度矩阵
    */
    void ComputeConvStiffness
    (
    const SG::Algebra::Matrix& coords, 
    const std::vector<SG::DataStructure::Common::Real>& h,
    _OUT SG::Algebra::Matrix& ke2
    );


    /** @brief 计算单元面辐射刚度矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] Emissivity 发射率/黑度（0-1）
     * @param [in] T 辐射面1绝对温度
     * @param [in] Text 辐射面2绝对温度
     * @param [out] ke4 单元边对流刚度矩阵
    */
    void ComputeRadStiffness
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::Common::Real& Emissivity,
    const std::vector<SG::DataStructure::Common::Real>& T,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& ke4
    );
    
    /** @brief 计算单元面对流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] material 材料特性
     * @param [in] Text 外部换热温度
     * @param [out] p3 单元面对流荷载矩阵
    */
    void ComputeConvLoad
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::FEM::ThermalMaterial& material,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& p3
    );
    
    /** @brief 计算单元面对流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] h 单元节点上对流换热系数
     * @param [in] Text 外部换热温度
     * @param [out] p3 单元面对流荷载矩阵
    */
    void ComputeConvLoad
    (
    const SG::Algebra::Matrix& coords, 
    const std::vector<SG::DataStructure::Common::Real>& h,
    const SG::DataStructure::Common::Real& Text,
    _OUT SG::Algebra::Matrix& p3
    );

    /** @brief 计算单元面热流荷载矩阵
     * @param [in] coords 单元面节点全局坐标
     * @param [in] q0 单元面热流量
     * @param [out] p2 单元面热流荷载矩阵
    */
    void ComputeHeatFluxLoad
    (
    const SG::Algebra::Matrix& coords, 
    const SG::DataStructure::Common::Real& q0,
    _OUT SG::Algebra::Matrix& p2
    );

    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void DataRecovery (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int subcaseId, SG::DataStructure::Common::Real time,  const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override;
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;
    static ElementCalculatorSP Create () {return std::make_shared<CHBDYGAREA3Calculator> ();}
    
private:
    SG::DataStructure::FEM::ElementTypes m_type;           ///< 单元类型
    static std::size_t s_nNode;                          ///< 单元节点数
    static std::size_t s_nDim;                           ///< 空间维度
    SG::DataStructure::Common::Real m_Area;                ///< 单元面积
};

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE